/**
 * Enhanced Session Manager for Room Recovery and Persistence
 * Handles comprehensive session persistence across page navigation and focus loss
 */

export class SessionManager {
    static ROOM_SESSION_KEY = 'chat_room_session';
    static ACTIVE_SESSION_KEY = 'active_room_session';
    static SESSION_TIMEOUT = 24 * 60 * 60 * 1000; // 24 hours
    static ACTIVITY_UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes
    
    static activityTimer = null;

    /**
     * Persist comprehensive room session data
     * @param {Object} roomData Room information
     * @param {Object} userData User information
     */
    static persistRoomSession(roomData, userData) {
        const sessionData = {
            userId: userData.id,
            nickname: userData.nickname,
            roomId: roomData.id,
            roomName: roomData.name,
            sessionToken: userData.sessionToken,
            joinedAt: userData.joinedAt,
            lastActivity: Date.now(),
            connectionState: 'active',
            persistedAt: Date.now(),
            isOwner: userData.isOwner || false,
            userPreferences: userData.preferences || {}
        };
        
        try {
            // Store in multiple locations for reliability
            localStorage.setItem(this.ROOM_SESSION_KEY, JSON.stringify(sessionData));
            sessionStorage.setItem(this.ACTIVE_SESSION_KEY, JSON.stringify(sessionData));
            
            // Store minimal recovery data in URL hash for immediate recovery
            this.updateURLHash(roomData.id, userData.id);
            
            console.log('Room session persisted:', sessionData);
            
            // Start activity tracking
            this.startActivityTracking();
            
        } catch (error) {
            console.error('Failed to persist room session:', error);
            throw new Error('Session persistence failed');
        }
    }

    /**
     * Get persisted session from multiple sources
     * @returns {Object|null} Session data or null if not found/expired
     */
    static getPersistedSession() {
        let sessionData = null;
        
        try {
            // 1. Check sessionStorage first (most recent)
            const sessionStr = sessionStorage.getItem(this.ACTIVE_SESSION_KEY);
            if (sessionStr) {
                sessionData = JSON.parse(sessionStr);
            }
            
            // 2. Fallback to localStorage
            if (!sessionData) {
                const localStr = localStorage.getItem(this.ROOM_SESSION_KEY);
                if (localStr) {
                    sessionData = JSON.parse(localStr);
                }
            }
            
            // 3. Check URL hash as last resort
            if (!sessionData) {
                sessionData = this.getSessionFromURL();
            }
            
            // Validate session freshness (24 hours max)
            if (sessionData && sessionData.persistedAt) {
                const age = Date.now() - sessionData.persistedAt;
                if (age > this.SESSION_TIMEOUT) {
                    console.log('Session expired, clearing...');
                    this.clearSession();
                    return null;
                }
            }
            
            return sessionData;
            
        } catch (error) {
            console.error('Failed to retrieve persisted session:', error);
            this.clearSession();
            return null;
        }
    }

    /**
     * Extract session data from URL hash
     * @returns {Object|null} Session data from URL or null
     */
    static getSessionFromURL() {
        try {
            if (!window.location.hash) return null;
            
            const hashParams = new URLSearchParams(window.location.hash.substring(1));
            if (hashParams.has('room') && hashParams.has('user')) {
                return {
                    roomId: hashParams.get('room'),
                    userId: hashParams.get('user'),
                    recoveryMode: true,
                    persistedAt: Date.now() - (23 * 60 * 60 * 1000) // Assume old but valid
                };
            }
            
            return null;
        } catch (error) {
            console.error('Failed to parse URL session:', error);
            return null;
        }
    }

    /**
     * Update URL hash with minimal session info
     * @param {string} roomId Room ID
     * @param {string} userId User ID
     */
    static updateURLHash(roomId, userId) {
        try {
            if (roomId && userId) {
                window.location.hash = `room=${roomId}&user=${userId}`;
            }
        } catch (error) {
            console.error('Failed to update URL hash:', error);
        }
    }

    /**
     * Clear all session data
     */
    static clearSession() {
        try {
            localStorage.removeItem(this.ROOM_SESSION_KEY);
            sessionStorage.removeItem(this.ACTIVE_SESSION_KEY);
            
            // Clear URL hash if it contains room data
            if (window.location.hash.includes('room=')) {
                window.location.hash = '';
            }
            
            // Stop activity tracking
            this.stopActivityTracking();
            
            console.log('Session data cleared');
            
        } catch (error) {
            console.error('Failed to clear session data:', error);
        }
    }

    /**
     * Update session activity timestamp
     */
    static updateSessionActivity() {
        const session = this.getPersistedSession();
        if (session) {
            session.lastActivity = Date.now();
            session.persistedAt = Date.now();
            
            try {
                localStorage.setItem(this.ROOM_SESSION_KEY, JSON.stringify(session));
                sessionStorage.setItem(this.ACTIVE_SESSION_KEY, JSON.stringify(session));
            } catch (error) {
                console.error('Failed to update session activity:', error);
            }
        }
    }

    /**
     * Start periodic activity tracking
     */
    static startActivityTracking() {
        if (this.activityTimer) {
            clearInterval(this.activityTimer);
        }
        
        this.activityTimer = setInterval(() => {
            this.updateSessionActivity();
        }, this.ACTIVITY_UPDATE_INTERVAL);
    }

    /**
     * Stop activity tracking
     */
    static stopActivityTracking() {
        if (this.activityTimer) {
            clearInterval(this.activityTimer);
            this.activityTimer = null;
        }
    }

    /**
     * Mark session as temporarily away (page hidden/unfocused)
     */
    static markSessionAsAway() {
        const session = this.getPersistedSession();
        if (session) {
            session.connectionState = 'away';
            session.lastActivity = Date.now();
            this.persistUpdatedSession(session);
        }
    }

    /**
     * Mark session as active (page visible/focused)
     */
    static markSessionAsActive() {
        const session = this.getPersistedSession();
        if (session) {
            session.connectionState = 'active';
            session.lastActivity = Date.now();
            this.persistUpdatedSession(session);
        }
    }

    /**
     * Update session with new data
     * @param {Object} sessionData Updated session data
     */
    static persistUpdatedSession(sessionData) {
        try {
            sessionData.persistedAt = Date.now();
            localStorage.setItem(this.ROOM_SESSION_KEY, JSON.stringify(sessionData));
            sessionStorage.setItem(this.ACTIVE_SESSION_KEY, JSON.stringify(sessionData));
        } catch (error) {
            console.error('Failed to persist updated session:', error);
        }
    }

    /**
     * Validate session with server
     * @param {Object} sessionData Session data to validate
     * @returns {Promise<Object>} Validation result
     */
    static async validateSessionWithServer(sessionData) {
        try {
            const response = await fetch('/api/sessions/validate', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    userId: sessionData.userId,
                    roomId: sessionData.roomId,
                    sessionToken: sessionData.sessionToken
                })
            });

            if (!response.ok) {
                throw new Error(`Server validation failed: ${response.status}`);
            }

            const validation = await response.json();
            
            // Update session with server response if valid
            if (validation.valid && validation.roomData) {
                this.updateSessionFromServer(validation.roomData);
            }
            
            return validation;
            
        } catch (error) {
            console.error('Session validation error:', error);
            return {
                valid: false,
                error: error.message,
                roomExists: false
            };
        }
    }

    /**
     * Update session data from server response
     * @param {Object} serverData Server validation response
     */
    static updateSessionFromServer(serverData) {
        if (serverData.userSession && serverData.room) {
            const sessionData = {
                ...serverData.userSession,
                roomId: serverData.room.id,
                roomName: serverData.room.name,
                lastActivity: Date.now(),
                persistedAt: Date.now(),
                connectionState: 'active'
            };
            
            this.persistUpdatedSession(sessionData);
        }
    }

    /**
     * Check if a session exists and is potentially valid
     * @returns {boolean} True if session exists
     */
    static hasValidSession() {
        const session = this.getPersistedSession();
        return session && session.userId && session.roomId;
    }

    /**
     * Get session info for display purposes
     * @returns {Object|null} Display-safe session info
     */
    static getSessionInfo() {
        const session = this.getPersistedSession();
        if (!session) return null;
        
        return {
            roomName: session.roomName,
            nickname: session.nickname,
            joinedAt: session.joinedAt,
            isOwner: session.isOwner,
            connectionState: session.connectionState,
            lastActivity: session.lastActivity
        };
    }

    /**
     * Prepare session for page unload
     */
    static prepareForUnload() {
        const session = this.getPersistedSession();
        if (session) {
            session.connectionState = 'unloading';
            session.lastActivity = Date.now();
            this.persistUpdatedSession(session);
        }
    }

    /**
     * Restore session after page load
     */
    static restoreAfterLoad() {
        const session = this.getPersistedSession();
        if (session) {
            session.connectionState = 'restored';
            session.lastActivity = Date.now();
            this.persistUpdatedSession(session);
            
            // Resume activity tracking
            this.startActivityTracking();
            
            return session;
        }
        return null;
    }

    /**
     * Create a recovery session for emergency situations
     * @param {string} roomId Room ID
     * @param {string} userId User ID
     * @param {string} nickname User nickname
     */
    static createRecoverySession(roomId, userId, nickname) {
        const recoverySession = {
            userId,
            nickname,
            roomId,
            roomName: 'Unknown Room',
            sessionToken: null,
            joinedAt: new Date().toISOString(),
            lastActivity: Date.now(),
            connectionState: 'recovery',
            persistedAt: Date.now(),
            isOwner: false,
            recoveryMode: true
        };
        
        this.persistUpdatedSession(recoverySession);
        return recoverySession;
    }
}